$OpenBSD: patch-src_iconview_qiconview_cpp,v 1.6 2007/12/28 17:45:04 espie Exp $
--- src/iconview/qiconview.cpp.orig	Fri Feb  2 15:01:07 2007
+++ src/iconview/qiconview.cpp	Sun Oct 28 01:16:23 2007
@@ -236,6 +236,7 @@ class QIconViewPrivate (public)
     QPoint dragStartPos;
     QFontMetrics *fm;
     int minLeftBearing, minRightBearing;
+    int rubberStartX, rubberStartY;
 
     uint mousePressed		:1;
     uint cleared		:1;
@@ -255,9 +256,11 @@ class QIconViewPrivate (public)
     uint firstSizeHint : 1;
     uint showTips		:1;
     uint pressedSelected	:1;
+    uint canStartRubber		:1;
     uint dragging		:1;
     uint drawActiveSelection	:1;
     uint inMenuMode		:1;
+    uint controlPressed         :1;
 
     QIconViewToolTip *toolTip;
     QPixmapCache maskCache;
@@ -1070,7 +1073,7 @@ void QIconViewItem::setText( const QString &text )
 
     if ( view ) {
 	if ( QRect( view->contentsX(), view->contentsY(),
-		    view->visibleWidth(), view->visibleHeight() ).
+		    view->visibleWidthSB(), view->visibleHeightSB() ).
 	     intersects( oR ) )
 	    view->repaintContents( oR.x() - 1, oR.y() - 1,
 				   oR.width() + 2, oR.height() + 2, FALSE );
@@ -1119,7 +1122,7 @@ void QIconViewItem::setPixmap( const QPixmap &icon )
 
     if ( view ) {
 	if ( QRect( view->contentsX(), view->contentsY(),
-		    view->visibleWidth(), view->visibleHeight() ).
+		    view->visibleWidthSB(), view->visibleHeightSB() ).
 	     intersects( oR ) )
 	    view->repaintContents( oR.x() - 1, oR.y() - 1,
 				   oR.width() + 2, oR.height() + 2, FALSE );
@@ -1155,7 +1158,7 @@ void QIconViewItem::setPicture( const QPicture &icon )
 
     if ( view ) {
 	if ( QRect( view->contentsX(), view->contentsY(),
-		    view->visibleWidth(), view->visibleHeight() ).
+		    view->visibleWidthSB(), view->visibleHeightSB() ).
 	     intersects( oR ) )
 	    view->repaintContents( oR.x() - 1, oR.y() - 1,
 				   oR.width() + 2, oR.height() + 2, FALSE );
@@ -1220,7 +1223,7 @@ void QIconViewItem::setPixmap( const QPixmap &icon, bo
 
 	    if ( view ) {
 		if ( QRect( view->contentsX(), view->contentsY(),
-			    view->visibleWidth(), view->visibleHeight() ).
+			    view->visibleWidthSB(), view->visibleHeightSB() ).
 		     intersects( oR ) )
 		    view->repaintContents( oR.x() - 1, oR.y() - 1,
 					   oR.width() + 2, oR.height() + 2, FALSE );
@@ -2750,10 +2753,12 @@ QIconView::QIconView( QWidget *parent, const char *nam
     d->lastItem = 0;
     d->count = 0;
     d->mousePressed = FALSE;
+    d->controlPressed = FALSE;
     d->selectionMode = Single;
     d->currentItem = 0;
     d->highlightedItem = 0;
     d->rubber = 0;
+    d->canStartRubber = FALSE;
     d->scrollTimer = 0;
     d->startDragItem = 0;
     d->tmpCurrentItem = 0;
@@ -3315,9 +3320,18 @@ void QIconView::doAutoScroll()
 	    alreadyIntersected = TRUE;
 	    QIconViewItem *item = c->items.first();
 	    for ( ; item; item = c->items.next() ) {
-		if ( d->selectedItems.find( item ) )
-		    continue;
-		if ( !item->intersects( nr ) ) {
+               if ( d->selectedItems.find( item ) ) {
+                   if ( item->intersects( nr ) && item->isSelected() && d->controlPressed ) {
+                       item->setSelected( FALSE );
+                       changed = TRUE;
+                       rr = rr.unite( item->rect() );
+                   } else if ( !item->intersects( nr ) && !item->isSelected() && d->controlPressed ) {
+                       item->setSelected( TRUE, TRUE );
+                       changed = TRUE;
+                       rr = rr.unite( item->rect() );
+                   } else
+                       continue;
+               } else if ( !item->intersects( nr ) ) {
 		    if ( item->isSelected() ) {
 			item->setSelected( FALSE );
 			changed = TRUE;
@@ -4508,34 +4522,25 @@ void QIconView::contentsMousePressEventEx( QMouseEvent
 	    }
 	}
     } else if ( ( d->selectionMode != Single || e->button() == RightButton )
-		&& !( e->state() & ControlButton ) )
+		&& !( e->state() & ControlButton ) && !( e->state() & ShiftButton ) )
 	selectAll( FALSE );
 
     setCurrentItem( item );
 
+    d->canStartRubber = FALSE;
     if ( e->button() == LeftButton ) {
-	if ( !item && ( d->selectionMode == Multi ||
-				  d->selectionMode == Extended ) ) {
-	    d->tmpCurrentItem = d->currentItem;
-	    d->currentItem = 0;
-	    repaintItem( d->tmpCurrentItem );
-	    if ( d->rubber )
-		delete d->rubber;
-	    d->rubber = 0;
-	    d->rubber = new QRect( e->x(), e->y(), 0, 0 );
-	    d->selectedItems.clear();
-	    if ( ( e->state() & ControlButton ) == ControlButton ) {
-		for ( QIconViewItem *i = firstItem(); i; i = i->nextItem() )
-		    if ( i->isSelected() )
-			d->selectedItems.insert( i, i );
-	    }
+	if ( !item && ( d->selectionMode == Multi || d->selectionMode == Extended ) )
+	{
+	    d->canStartRubber = TRUE;
+	    d->rubberStartX = e->x();
+	    d->rubberStartY = e->y();
 	}
-
 	d->mousePressed = TRUE;
+	d->controlPressed = ( ( e->state() & ControlButton ) == ControlButton );
     }
 
  emit_signals:
-    if ( !d->rubber ) {
+    if ( !d->canStartRubber ) {
 	emit mouseButtonPressed( e->button(), item, e->globalPos() );
 	emit pressed( item );
 	emit pressed( item, e->globalPos() );
@@ -4579,6 +4584,7 @@ void QIconView::contentsMouseReleaseEvent( QMouseEvent
     d->mousePressed = FALSE;
     d->startDragItem = 0;
 
+    d->canStartRubber = FALSE;
     if ( d->rubber ) {
 	QPainter p;
 	p.begin( viewport() );
@@ -4668,7 +4674,22 @@ void QIconView::contentsMouseMoveEvent( QMouseEvent *e
 	    if ( d->tmpCurrentItem )
 		repaintItem( d->tmpCurrentItem );
 	}
-    } else if ( d->mousePressed && !d->currentItem && d->rubber ) {
+    } else if ( d->mousePressed && ((!d->currentItem && d->rubber) || d->canStartRubber) ) {
+	if ( d->canStartRubber ) {
+	    d->canStartRubber = FALSE;
+	    d->tmpCurrentItem = d->currentItem;
+	    d->currentItem = 0;
+	    repaintItem( d->tmpCurrentItem );
+	    delete d->rubber;
+	    d->rubber = new QRect( d->rubberStartX, d->rubberStartY, 0, 0 );
+	    d->selectedItems.clear();
+	    if ( ( e->state() & ControlButton ) == ControlButton ||
+	         ( e->state() & ShiftButton ) == ShiftButton ) {
+		for ( QIconViewItem *i = firstItem(); i; i = i->nextItem() )
+		    if ( i->isSelected() )
+			d->selectedItems.insert( i, i );
+	    }
+	}
 	doAutoScroll();
     }
 }
@@ -5245,11 +5266,11 @@ QIconViewItem* QIconView::findItem( Direction dir,
 	d->findContainers( dir, relativeTo, searchRect);
 
     cList->first();
-    while ( cList->current() && !centerMatch ) {
+    while ( cList->current() ) {
 	QPtrList<QIconViewItem> &list = (cList->current())->items;
 	for ( item = list.first(); item; item = list.next() ) {
 	    if ( neighbourItem( dir, relativeTo, item ) &&
-		 searchRect.contains( item->rect().center() ) &&
+		 searchRect.intersects( item->rect() ) &&
 		 item != currentItem() ) {
  		int ml = (relativeTo - item->rect().center()).manhattanLength();
 		if ( centerMatch ) {
@@ -5472,8 +5493,8 @@ void QIconView::insertInGrid( QIconViewItem *item )
 	}
 	item->dirty = FALSE;
     } else {
-	QRegion r( QRect( 0, 0, QMAX( contentsWidth(), visibleWidth() ),
-			  QMAX( contentsHeight(), visibleHeight() ) ) );
+	QRegion r( QRect( 0, 0, QMAX( contentsWidth(), visibleWidthSB() ),
+			  QMAX( contentsHeight(), visibleHeightSB() ) ) );
 
 	QIconViewItem *i = d->firstItem;
 	int y = -1;
@@ -5731,7 +5752,7 @@ QIconViewItem *QIconView::makeRowLayout( QIconViewItem
 	    QIconViewItem *item = begin;
 	    for (;;) {
 		x += d->spacing + item->width();
-		if ( x > visibleWidth() && item != begin ) {
+		if ( x > visibleWidthSB() && item != begin ) {
 		    item = item->prev;
 		    break;
 		}
@@ -5756,7 +5777,7 @@ QIconViewItem *QIconView::makeRowLayout( QIconViewItem
 		int x;
 		if ( item == begin ) {
 		    if ( reverse )
-			x = visibleWidth() - d->spacing - item->width();
+			x = visibleWidthSB() - d->spacing - item->width();
 		    else
 			x = d->spacing;
 		} else {
@@ -5792,7 +5813,7 @@ QIconViewItem *QIconView::makeRowLayout( QIconViewItem
 		    i += r;
 		    x = i * d->rastX + sp * d->spacing;
 		}
-		if ( x > visibleWidth() && item != begin ) {
+		if ( x > visibleWidthSB() && item != begin ) {
 		    item = item->prev;
 		    break;
 		}
@@ -5855,7 +5876,7 @@ QIconViewItem *QIconView::makeRowLayout( QIconViewItem
 	    QIconViewItem *item = begin;
 	    for (;;) {
 		y += d->spacing + item->height();
-		if ( y > visibleHeight() && item != begin ) {
+		if ( y > visibleHeightSB() && item != begin ) {
 		    item = item->prev;
 		    break;
 		}
@@ -6169,7 +6190,9 @@ void QIconView::rebuildContainers()
 	    item->d->container2 = 0;
 	    c->items.append( item );
 	    item = item->next;
-	} else if ( c->rect.intersects( item->rect() ) ) {
+	} else if ( c->rect.intersects( item->rect() ) && (
+			( d->arrangement == LeftToRight && item->y() >= c->rect.y() ) ||
+			( d->arrangement == TopToBottom && item->x() >= c->rect.x() ) ) ) {
 	    item->d->container1 = c;
 	    c->items.append( item );
 	    c = c->n;
@@ -6402,4 +6425,24 @@ bool QIconView::isRenaming() const
 #endif
 }
 
+int QIconView::visibleWidthSB() const
+{
+    if ( vScrollBarMode() != Auto )
+        return visibleWidth();
+    
+    int offset = verticalScrollBar()->isVisible() ? 0
+        : style().pixelMetric( QStyle::PM_ScrollBarExtent, verticalScrollBar() );
+    return QMAX( 0, visibleWidth() - offset );
+}
+
+int QIconView::visibleHeightSB() const
+{
+    if ( hScrollBarMode() != Auto )
+        return visibleHeight();
+    
+    int offset = horizontalScrollBar()->isVisible() ? 0
+        : style().pixelMetric( QStyle::PM_ScrollBarExtent, horizontalScrollBar() );
+    return QMAX( 0, visibleHeight() - offset );
+}
+        
 #endif // QT_NO_ICONVIEW
